﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using BrainTechLLC.Silverlight.Controls;

namespace BrainTechLLC.Silverlight.ClientApplication
{
    public partial class FlexibleTypeEditor : UserControl
    {
        public event EventHandler<ObjectEventArgs<LocationInt>> RequestGoLocation;
        public event EventHandler<ObjectEventArgs<LocationInt>> RequestEditGameLocation;
        public event EventHandler<ObjectEventArgsNonRef<long>> RequestEditID;

        //public override void SetVisualizedData(DataVisualizer vis, object o) { EditObj = o; base.SetVisualizedData(vis, o); }
        public Type VisualizeType { get { return typeof(object); } }
        public string VisualizerName { get { return "FlexibleTypeEditor"; } }

        public static readonly DependencyProperty EditObjProperty = DependencyProperty.Register(
            "EditObj", typeof(object), typeof(FlexibleTypeEditor), new PropertyMetadata(null, new PropertyChangedCallback(EditObjChanged)));

        public object EditObj
        {
            get { return (object)GetValue(EditObjProperty); }
            set { SetValue(EditObjProperty, value); }
        }

        public static readonly DependencyProperty IsWindowlessProperty = DependencyProperty.Register(
            "IsWindowless", typeof(bool), typeof(FlexibleTypeEditor), new PropertyMetadata(true, new PropertyChangedCallback(IsWindowlessChanged)));

        public bool IsWindowless
        {
            get { return (bool)GetValue(IsWindowlessProperty); }
            set { SetValue(IsWindowlessProperty, value); }
        }

        private static void IsWindowlessChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FlexibleTypeEditor t = (FlexibleTypeEditor)d;
            t.IsWindowless = (bool)e.NewValue;
            t.UpdateWindowless();
        }

        public static readonly DependencyProperty HideHeaderProperty = DependencyProperty.Register(
            "HideHeader", typeof(bool), typeof(FlexibleTypeEditor), new PropertyMetadata(false, new PropertyChangedCallback(HideHeaderChanged)));

        public bool HideHeader
        {
            get { return (bool)GetValue(HideHeaderProperty); }
            set { SetValue(HideHeaderProperty, value); }
        }

        private static void HideHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FlexibleTypeEditor t = (FlexibleTypeEditor)d;
            t.HideHeader = (bool)e.NewValue;
            t.UpdateWindowless();
        }

        public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register(
            "IsOpen", typeof(bool), typeof(FlexibleTypeEditor), new PropertyMetadata(true, new PropertyChangedCallback(IsOpenChanged)));

        public bool IsOpen
        {
            get { return (bool)GetValue(IsOpenProperty); }
            set { SetValue(IsOpenProperty, value); }
        }

        private static void IsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FlexibleTypeEditor t = (FlexibleTypeEditor)d;
            t.IsOpen = (bool)e.NewValue;
            t.UpdateOpen();
        }

        public Func<WindowContainer, bool> FilterWindowlessMode { get { return null; } set { ForEachEditControl((item) => item.FilterWindowlessMode = value); } }
        public Func<WindowContainer, bool> FilterHideHeader { get { return null; } set { ForEachEditControl((item) => item.FilterHideHeader = value); } }

        public DataVisualizer EditGameThingVisualizer
        {
            get { return editGameThing; }
        }

        public void ForEachEditControl(Action<DataVisualizer> action)
        {
            action(editGameLocation);
            action(editMedia);
            action(editGameCharTemplate);
            action(editArea);
            action(editGameThing);
            action(editItem);
            action(editItemTemplate);
            action(editLocationEdge);
            action(editReset);
        }

        public void UpdateWindowless()
        {
            bool windowless = IsWindowless;
            ForEachEditControl((item) => item.WindowlessMode = windowless);

            bool hideHeader = HideHeader;
            ForEachEditControl((item) => item.HideHeader = hideHeader);
        }

        public void UpdateOpen()
        {
            bool open = IsOpen;
            ForEachEditControl((item) => item.IsOpen = open);
        }

        public static void HandleChange<T2>(DependencyObject d, DependencyPropertyChangedEventArgs e, Action<FlexibleTypeEditor, T2> action)
        {
            d.HandleChange<FlexibleTypeEditor, T2>(e, action, (t) => t.UpdateBindings());
        }

        private static void EditObjChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FlexibleTypeEditor t = (FlexibleTypeEditor)d;
            t.EditObj = e.NewValue;
            t.UpdateBindings();
        }

        public void CollapseAll()
        {
            ForEachEditControl((item) => item.Visibility = Visibility.Collapsed);
        }

        public void UpdateBindings()
        {
            this.DataContext = EditObj;

            CollapseAll();

            if (EditObj is GameLocation)
            {
                editGameLocation.Visibility = Visibility.Visible;
                editGameLocation.DataToVisualize = EditObj;
            }
            else if (EditObj is Item)
            {
                editItem.Visibility = Visibility.Visible;
                editItem.DataToVisualize = EditObj;
            }
            else if (EditObj is ItemTemplate)
            {
                editItemTemplate.Visibility = Visibility.Visible;
                editItemTemplate.DataToVisualize = EditObj;
            }
            else if (EditObj is Area)
            {
                editArea.Visibility = Visibility.Visible;
                editArea.DataToVisualize = EditObj;
            }
            else if (EditObj is Media)
            {
                editMedia.Visibility = Visibility.Visible;
                editMedia.DataToVisualize = EditObj;
            }
            else if (EditObj is Reset)
            {
                editReset.Visibility = Visibility.Visible;
                editReset.DataToVisualize = EditObj;
            }
            else if (EditObj is GameCharTemplate)
            {
                editGameCharTemplate.Visibility = Visibility.Visible;
                editGameCharTemplate.DataToVisualize = EditObj;
            }
            else if (EditObj is LocationEdge)
            {
                editLocationEdge.Visibility = Visibility.Visible;
                editLocationEdge.DataToVisualize = EditObj;
            }
            else
            {
                editGameThing.Visibility = Visibility.Visible;
                editGameThing.DataToVisualize = EditObj;
            }
        }

        public FlexibleTypeEditor()
        {
            // Required to initialize variables
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
        }

        private void editArea_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        private void editItem_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        private void editItemTemplate_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        private void editGameThing_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        private void editGameLocation_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        public void OnRequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            if (RequestEditID != null)
                RequestEditID(sender, e);
        }

        public void OnRequestGoToLocation(object sender, ObjectEventArgs<LocationInt> e)
        {
            if (RequestGoLocation != null)
                RequestGoLocation(this, e);
        }

        private void editReset_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        private void editLocationEdge_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        private void editGameCharTemplate_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }

        private void editGameLocation_RequestGoLocation(object sender, ObjectEventArgs<LocationInt> e)
        {
            OnRequestGoToLocation(sender, e);
        }

        public void OnRequestEditGameLocation(object sender, ObjectEventArgs<LocationInt> e)
        {
            if (RequestEditGameLocation != null)
                RequestEditGameLocation(this, e);
        }

        private void editGameLocation_RequestEditGameLocation(object sender, ObjectEventArgs<LocationInt> e)
        {
            OnRequestEditGameLocation(sender, e);
        }

        private void editMedia_RequestEditID(object sender, ObjectEventArgsNonRef<long> e)
        {
            OnRequestEditID(sender, e);
        }
    }
}